package org.light.simpleauth.verb;

import java.util.ArrayList;
import java.util.List;

import org.light.core.Verb;
import org.light.core.Writeable;
import org.light.domain.Domain;
import org.light.domain.JavascriptBlock;
import org.light.domain.JavascriptMethod;
import org.light.domain.Method;
import org.light.domain.Signature;
import org.light.domain.Statement;
import org.light.domain.Type;
import org.light.easyui.EasyUIPositions;
import org.light.exception.ValidateException;
import org.light.utils.StringUtil;
import org.light.utils.WriteableUtil;

public class LoginUser extends Verb implements EasyUIPositions {

	@Override
	public Method generateDaoImplMethod() throws Exception {
		return null;
	}	

	@Override
	public Method generateDaoMethodDefinition() throws Exception {
		return null;
	}
	@Override
	public Method generateServiceMethodDefinition() throws Exception {
		return null;
	}
	@Override
	public Method generateServiceImplMethod() throws Exception  {
		if (this.denied) return null;
		else {
			Method method = new Method();
			method.setStandardName("Login"+StringUtil.capFirst(this.domain.getStandardName()));
			method.setReturnType(new Type("Result<"+this.domain.getCapFirstDomainNameWithSuffix()+">"));		
			method.addSignature(new Signature(1, this.domain.findFieldByFixedName("userName").getSnakeFieldName(), "String"));
			method.addSignature(new Signature(2, this.domain.findFieldByFixedName("password").getSnakeFieldName(), "String"));
			method.addAdditionalImport("crate::utils::encrypt_util::verify_password");
			List<Writeable> sList = new ArrayList<Writeable>();

			FindUserShadow findShadow = new FindUserShadow(this.domain,this.domain.getDbType());
	
			sList.add(new Statement(85000L,1,"let "+this.domain.getSnakeDomainName()+" = "+StringUtil.getSnakeName(findShadow.getVerbName())+"("+this.domain.findFieldByFixedName("userName").getSnakeFieldName()+").await?;"));
			sList.add(new Statement(86000L,1,"if verify_password("+this.domain.findFieldByFixedName("password").getSnakeFieldName()+", "+this.domain.getSnakeDomainName()+"."+this.domain.findFieldByFixedName("salt").getSnakeFieldName()+".clone(), "+this.domain.getSnakeDomainName()+"."+this.domain.findFieldByFixedName("password").getSnakeFieldName()+".clone()).await? {"));
			sList.add(new Statement(87000L,2,"Ok("+this.domain.getSnakeDomainName()+".clone())"));
			sList.add(new Statement(88000L,1,"} else {"));
			sList.add(new Statement(89000L,2,"Err(Error::WrongPassword)"));
			sList.add(new Statement(90000L,1,"}"));
			
			method.setMethodStatementList(WriteableUtil.merge(sList));
			return method;
		}
	}
	
	public LoginUser(Domain domain) throws ValidateException{
		super();
		this.domain = domain;
		this.denied = domain.isVerbDenied("LoginUser");
		this.setVerbName("Login"+StringUtil.capFirst(this.domain.getStandardName()));
		this.setLabel("登录");
		if  (domain.getLanguage().equalsIgnoreCase("english"))  this.setLabel("LoginUser");
	}

	@Override
	public Method generateControllerMethod() throws Exception {
		if (this.denied) return null;
		else {
			Method method = new Method();
			method.setStandardName("Login" + StringUtil.capFirst(this.domain.getStandardName()));
			method.addSignature(new Signature(1,"mut session","WritableSession"));
			method.addSignature(new Signature(2,"Json(input)","Json<LoginInput>"));
			method.setReturnType(new Type("String"));
			
			List<Writeable> sList = new ArrayList<Writeable>();

			sList.add(new Statement(85000L,1,"//validate_payload(&input)?;"));
			sList.add(new Statement(86000L,1,"let "+this.domain.getSnakeDomainName()+" = service_login_"+this.domain.getSnakeDomainName()+"(input."+this.domain.findFieldByFixedName("userName").getSnakeFieldName()+",input."+this.domain.findFieldByFixedName("password").getSnakeFieldName()+")"));
			sList.add(new Statement(87000L,2,".await"));
			sList.add(new Statement(88000L,2,".map_err(|_| Error::WrongCredentials).unwrap();"));
			sList.add(new Statement(89000L,1,"let token = jwt_util::sign("+this.domain.getSnakeDomainName()+"."+this.domain.getDomainId().getSnakeFieldName()+").unwrap();"));
			sList.add(new Statement(91000L,1,"session.insert(\"token\",token.clone());"));
			sList.add(new Statement(92000L,1,"let result = serde_json::to_string_pretty(&TokenPayload {"));
			sList.add(new Statement(93000L,2,"success:true,"));
			sList.add(new Statement(94000L,2,"token: token.clone()"));
			sList.add(new Statement(95000L,1,"}).unwrap();"));
			sList.add(new Statement(96000L,1,"result"));
			
			method.setMethodStatementList(WriteableUtil.merge(sList));
			return method;
		}
	}	
	@Override
	public JavascriptBlock generateEasyUIJSButtonBlock() throws Exception {
		return null;		
	}
	@Override
	public JavascriptMethod generateEasyUIJSActionMethod() throws Exception {
		return null;
	}
}
